#################################################################################
# Example of FSDEVS network model for a generator.                              #
# There are three characteristics:                                              #
#  (1) generation mode: automatic or triggered by signal: bAuto                 #
#  (2) generating spectrum: distribution of generated class: OutTable           #
#  (3) inter-generating time: IntGenTimeRV                                      #
# Author: moonho.hwang@gmail.com                                                #
#   Date: Oct.20.2011                                                           #
#################################################################################
from XSY.DEVS.FSDEVS import * 
from XSY.DEVS.SimEngine import SimEngine
from XSY.DEVS.CoupledDEVS import *
from XSY.Set.Interval import *
from XSY.DEVS.ReachGen import *

class A:
   '''A flow entity class'''
   pass

class B:
   '''Another flow entity class'''
   pass

class Generator(FSDEVS):
   ''' an atomic FSDEVS of a generator'''
   def __init__(m, n, bAuto, OutTable, IntGenTimeRV, parent=None):
      '''constructor, bAuto is an indicator for keeping generating or generating only receiving the input signal ?pull; OutTable is the output distribution dictionary (value, probability); IntGenTimeRV is the  '''
      # make the base class FSDEVS
      FSDEVS.__init__(m, n, parent) 
      m.bAuto = bAuto 
      m.OutTable = OutTable
      m.IntGenTimeRV = IntGenTimeRV
      m.count = 0
      # make ports  
      m.addOutputPorts('!out')
      m.addInputPorts('?pull')

   def rv_delta_0(m):
      '''the initial state probability'''
      m.count = 0
      if m.bAuto == True:
         return DRV({'G':1})
      else:
         return DRV({'W':1})

   def rv_tau(m):
      '''random lifespan scheduling function'''
      if m.phase == 'G':
         return m.IntGenTimeRV 
      else:
         return DRV({float('inf'):1})

   def rv_delta_x(m, x):
      '''random external transition function'''
      if m.bAuto :
         return DRV({(False, m.phase):1})
      else:
         if m.phase == 'W': m.phase = 'G'
         else:              m.phase = 'W' 
         return DRV({(True,  m.phase):1})

   def rv_delta_y(m):
      '''random output and internal transition function'''
      m.count = m.count + 1
      if m.bAuto == False:
         m.phase = 'W'

      s = m.get_state()
      y_s = {}
      for o, p in m.OutTable.iteritems():
         y = PortValue(m.OP['!out'], o()) # instanciate o()
         y_s[(y,s)]=p   

      return DRV(y_s) #(y,s) in (Y x S)

   def get_state(m):
      '''get dest'''
      return m.phase

   def set_state(m, s):
      '''set dest'''
      m.phase = s

   def get_statistics_str(self):
      ''''''
      s = "|g|=%d, %s"%(self.count, FSDEVS.get_statistics_str(self))
      return s

def runSimulation(md):
   engine = SimEngine(md)

   #---- setting StepByStep and DES simulation only ----
   engine.StepByStep = True
   engine.sfactor = float('inf')
   #----------------------------------------------------
   engine.runInteractiveMenu()

if __name__ == '__main__':
   print '''
#######################################################
# Example of FSDEVS generator model 
# Author: moonho.hwang@gmail.com
#   Date: Apr.08.2012
######################################################
   '''

   md1 = Generator(n="Gen", bAuto = True, OutTable={A:.7, B:.3}, IntGenTimeRV=TInterval(2,5)) 
   runSimulation(md1)

   print "good bye~!" 
    
